#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
//#include <sys/wait.h>
#include <unistd.h>

#include <io.h>
#include <fcntl.h>
#include <cstdio>
#include <exception>
//#include <stdexcept>

#include <vector>

#include <jansson.h>

#define SEPARATE_DIR "\\"


using namespace std;


char *currentPath=NULL;


typedef struct {
	int index;
	int otl_var_dbtype;
	char name[300];
	long dbsize;

}ColumnInfo;



//
//typedef enum {
//
//    source='source',
//    hostip='hostip',
//    port='port',
//    query='query',
//    outputfile='outputfile',
//    separated='separated',
//    ODBC='ODBC',
//    datasource='datasource',
//    execute='execute',
//    order='order'
//
//}enum_job_extract;

//typedef enum { query, outputfile } enum_job_extract;

typedef struct job_extract {
	char *query;
	char *outputfile;
	char *separated;
	char *odbc;
	char *source;
	char *execute;
	char *order;
	char *hostip;
	int *port;
	char *datasource;
} job_extract;


typedef struct job_transform_columns {
    char* name;
    char* operation;
    char* mode;
    char* separated;
    char* inputfilename;
} job_transform_columns;


typedef struct job_transform {

char* source;
char* hostip;
int* port;
char* inputfilename;
char* outputfile;
vector<job_transform_columns> cols;
char* execute;
int* order;

} job_transform;


typedef struct job_mapping {
	char *query;
	char *filename;
	char *separated;
	char *odbc;


} job_mapping;



typedef struct scheduler_job {
    job_extract e;
    job_transform t;
    job_mapping m;
} scheduler_json;



//vector<scheduler_json> jobs;


json_error_t *error;


//enum_job_extract enum_job_e;




job_extract
get_all_itens_extract_json( json_t *t, char* key="extraction" ){

    job_extract job_e;
    json_t *extraction_j;

    extraction_j	=	json_object_get(t,key);

    if (json_is_object(extraction_j)) {

        job_e.execute=  (char*) json_string_value(
                                    json_object_get(extraction_j,
                                    "execute"));

        job_e.datasource=  (char*) json_string_value(
                                    json_object_get(extraction_j,
                                        "datasource"));

        job_e.hostip=  (char*) json_string_value(
                                    json_object_get(extraction_j,
                                        "hostip"));

        job_e.odbc=  (char*) json_string_value(
                                    json_object_get(extraction_j,
                                        "ODBC"));

        job_e.order=  (char*) json_string_value(
                                    json_object_get(extraction_j,
                                        "order"));

        job_e.outputfile=  (char*) json_string_value(
                                    json_object_get(extraction_j,
                                        "outputfile"));

        job_e.port=  (int*) json_integer_value(
                                    json_object_get(extraction_j,
                                        "port"));

        job_e.query=  (char*) json_string_value(
                                    json_object_get(extraction_j,
                                        "query"));

        job_e.separated=  (char*) json_string_value(
                                    json_object_get(extraction_j,
                                        "separated"));

        job_e.source=  (char*) json_string_value(
                                    json_object_get(extraction_j,
                                        "source"));

    }

    return job_e;
}

job_transform
get_all_itens_transform_json( json_t *t, char *key="transformation" ){

    job_transform job_t;
    json_t *transform_j,*transform_cols_j,
            *transform_col_j,*transform_col_item_j;

    try{

        //transformation
        transform_j	=	json_object_get(t, key);

        if (json_is_object(transform_j)) {

            job_t.execute=  (char*) json_string_value(
                json_object_get(transform_j,
                            "execute"));

            job_t.hostip=  (char*) json_string_value(
                json_object_get(transform_j,
                            "hostip"));

            job_t.order=  (int*) json_integer_value(
                json_object_get(transform_j,
                            "order"));

            job_t.outputfile=  (char*) json_string_value(
                json_object_get(transform_j,
                            "outputfile"));

            job_t.port=  (int*) json_integer_value(
                json_object_get(transform_j,
                            "port"));

            job_t.source=  (char*) json_string_value(
                json_object_get(transform_j,
                            "source"));

            job_t.inputfilename=  (char*) json_string_value(
                json_object_get(transform_j,
                            "inputfilename"));

            transform_cols_j	=	json_object_get(transform_j,
                                               "columns");

            for (int y = 0;
                y < (int) json_array_size(transform_cols_j); ++y) {

                transform_col_j=	json_array_get(transform_cols_j,y);

                transform_col_item_j	=	json_object_get(
                                        transform_col_j,"column");

                //char *p;//=new char[10];
                //p=(char*) json_string_value(
                //            json_object_get(transform_col_item_j,
                //                                        "name"));
                job_transform_columns cols;

                cols.name   =  (char*) json_string_value(
                                        json_object_get(transform_col_item_j,
                                        "name"));

                cols.mode=  (char*) json_string_value(
                                        json_object_get(transform_col_item_j,
                                        "mode"));

                cols.operation=  (char*) json_string_value(
                                        json_object_get(transform_col_item_j,
                                        "operation"));

                cols.inputfilename=  (char*) json_string_value(
                                        json_object_get(transform_col_item_j,
                                        "inputfilename"));

                cols.separated=  (char*) json_string_value(
                                        json_object_get(transform_col_item_j,
                                        "separated"));

                job_t.cols.push_back(cols);

            }

        }

    }catch(exception &e)  // intercept OTL exceptions
	{
        //cout<<" error "<<e.getMessage()<<endl;
        cerr <<"Erro: "<< e.what() << '\n';
		//throw "Can't use letters";

	}

    return job_t;
}


char *
get_json_string_value(json_t* j_t, const char *item){

    return (char*) json_string_value(json_object_get(j_t,item));

}



char *
ExtractFilePath(const char *FileName, const char * separate)
{
    //std::string s = FileName;
    int Len = strlen (FileName);// s.length();

    while(1)
    {

        //if( strcmp (parts[0],parts[1]) != 0){
        if( FileName[Len] != separate[0]){

        //if( strncpy() != strncpy(separate,0,1) )
            Len--;

            if( Len < 20)
                break;
        }
        else
        {
            Len++;
            //printf("Len=%i\n",Len);
            //char *NameF = new char[Len+1];

            char* NameF=NULL;
            int a;
            //NameF= (char*)malloc(sizeof(char)*Len);
            //NameF=NULL;
            //char *NameF = new char[Len+1];
            NameF = (char*)malloc(sizeof(char)*Len);
//memcpy (NameF, (const char*)"");
            //NameF="";

            for(a=0; a<Len; a++){

               // printf("%i, %s\n",a, substr(FileName, a,a));
                //NameF[a] = FileName[a];
                //printf("%i, %s\n",a, substr(FileName, a,a));
//printf("%s",substr(FileName, a,a));
                //memcpy (NameF, substr(FileName, a,a),10);

               // if( NameF[a]==FileName[a]){

               // }

                NameF[a]=FileName[a];
                //printf("%s", FileName[a]);
               // strcat(NameF,FileName[a]);//substr(FileName, a,a) );
            }


//                //NameF[a] = FileName[s.length()-(s.length()-Len)+a];
//            NameF[Len+1] = '\0';
//printf("%s",substr(NameF,1,Len));
            NameF[Len] = '\0';

            return NameF;//substr(NameF,1,Len);
        }
    }

    return "";
}


char *
replace(char *s, char old, char novo)
{
	char *p = s;

	while(*p)
	{
		if(*p == old)
			*p = novo;

		++p;
	}

	return s;
}





int
starting_job_transform(job_transform job){

    FILE *fp;
    int status;
    char path[1035];
    char *outfilename;//= new char [3024];

    outfilename = (char*)malloc(sizeof(char)*3024);
    char* aux;

    aux = (char*)malloc(sizeof(char)*555);

    for(int i=0;i<job.cols.size();i++){
        //char *v;

        //v= job.cols.at(i).name;

        strcat(aux, " -columns");

        strcat(aux," -name \"");
        strcat(aux,job.cols.at(i).name);
        strcat(aux,"\"");

        //v= job.cols.at(i).separated;
        strcat(aux," -separated \"");
        strcat(aux,job.cols.at(i).separated);
        strcat(aux,"\"");

       // v= job.cols.at(i).mode;
        strcat(aux," -operation \"");
        strcat(aux,job.cols.at(i).operation);
        strcat(aux,"\"");

        //v= job.cols.at(i).mode;
        strcat(aux," -mode \"");
        strcat(aux,job.cols.at(i).mode);
        strcat(aux,"\"");

        //v= job.cols.at(i).inputfilename;
        strcat(aux," -inputfilename \"");
        strcat(aux,job.cols.at(i).inputfilename);
        strcat(aux,"\"");
    }

    wsprintf(outfilename,"%s -inputfile \"%s\" -separated \"s\" -outputfile \"%s\" %s",
                            //currentPath,
                            //SEPARATE_DIR,
                            job.source,
                            job.inputfilename,
                            job.outputfile,
                            aux
                            //job.datasource,
                            //job.query
                            );
//cout<<outfilename<<endl;
//system("pause");

    /* Open the command for reading. */
    fp = popen(outfilename, "r");
    if (fp == NULL) {
        printf("Failed to run command\n" );
        exit;
    }

    /* Read the output a line at a time - output it. */
    while (fgets(path, sizeof(path)-1, fp) != NULL) {
        printf("%s", path);
    }

    /* close */
    pclose(fp);

}


int
starting_job_extract(job_extract job){

    FILE *fp;
    int status;
    char path[1035];
    char *outfilename;//= new char [3024];

    outfilename = (char*)malloc(sizeof(char)*
                                (strlen(currentPath)+1024)
                                   );

    wsprintf(outfilename,"%s -odbc \"%s\" -separated \"%s\" -outputfile \"%s\" -datasource \"%s\" -query \"%s\"",
                            //currentPath,
                            //SEPARATE_DIR,
                            job.source,
                            job.odbc,
                            job.separated,
                            job.outputfile,
                            job.datasource,
                            job.query);


cout<<outfilename<<endl;
system("pause");

    /* Open the command for reading. */
    fp = popen(outfilename, "r");
    if (fp == NULL) {
        printf("Failed to run command\n" );
        exit;
    }

    /* Read the output a line at a time - output it. */
    while (fgets(path, sizeof(path)-1, fp) != NULL) {
        printf("%s", path);
    }

    /* close */
    pclose(fp);

}

void
starting_jobs( vector<scheduler_json> jobs ){

    unsigned int i;
    job_extract job_e;
    job_transform job_t;
    char *aux;
    //job_e=(job_extract*)malloc(sizeof(job_extract)*1);

    for( i = 0; i < jobs.size(); i++)
    {
        job_e.datasource=jobs[i].e.datasource;
        job_e.execute=jobs[i].e.execute;
        job_e.hostip=jobs[i].e.hostip;
        job_e.odbc=jobs[i].e.odbc;
        job_e.order=jobs[i].e.order;
        job_e.outputfile=jobs[i].e.outputfile;
        job_e.port=jobs[i].e.port;
        job_e.query=jobs[i].e.query;
        job_e.separated=jobs[i].e.separated;
        job_e.source=jobs[i].e.source;

        aux=job_e.execute;//new char[2];
        //char *x="yes";
        //p=job_e.execute;

        if( strcmp(aux,"yes")==0){
            starting_job_extract(job_e);
        }



        //job_e.datasource=jobs[i].e.datasource;
        job_t.execute=jobs[i].t.execute;
        job_t.hostip=jobs[i].t.hostip;
        job_t.inputfilename=jobs[i].t.inputfilename;
        job_t.order=jobs[i].t.order;
        job_t.outputfile=jobs[i].t.outputfile;
        job_t.port=jobs[i].t.port;
        job_t.cols=jobs[i].t.cols;
        //job_e.separated=jobs[i].e.separated;
        job_t.source=jobs[i].t.source;

        aux=job_t.execute;

        if( strcmp(aux,"yes")==0){
             starting_job_transform(job_t);
        }


        //cout<<jobs[i].e.query<<endl;
    }

}

void
typenode( json_t *t){

    switch(json_typeof(t)) {

        case JSON_NULL:{cout<<"null"<<endl;}break;

        case JSON_TRUE:{}

        case JSON_FALSE:{}

        case JSON_INTEGER:{}

        case JSON_REAL:{}

        case JSON_STRING:{}

        case JSON_ARRAY:{cout<<"array"<<endl;}break;
        case JSON_OBJECT:{cout<<"object"<<endl;}break;
        default:{cout<<"nada"<<endl;}break;
            /* not reached */

 }

}

vector<scheduler_json>
load_jobs( char *filename ){

    vector<scheduler_json> jobs;

	try{
        json_t *json_node;
        json_t *data_j;
        json_t *job_j;

		json_node = json_load_file(filename, 0, error);

        if( json_node ){

            if( json_typeof(json_node)== JSON_ARRAY){

                for (int i = 0; i < (int) json_array_size(json_node) ; ++i) {

                    data_j = json_array_get(json_node,i);

                    if (json_is_object(data_j)) {

                        scheduler_json jobs_;

                        job_j	=	json_object_get(data_j,"job");

                        jobs_.e   =  get_all_itens_extract_json(job_j,
                                                        "extraction");

                        jobs_.t   =  get_all_itens_transform_json(job_j,
                                                        "transformation");

                        jobs.push_back(jobs_);
                    }
                }

            }
        }


	}catch(exception &e)  // intercept OTL exceptions
	{
        //cout<<" error "<<e.getMessage()<<endl;
        cerr <<"Erro: "<< e.what() << '\n';
		//throw "Can't use letters";

	}


    return jobs;
}


void
starting_task(void *p){

    FILE *fp;
    int status;
    char path[1035];

    /* Open the command for reading. */
    fp = popen("C:\\workspace\\c\\etm-extract\\bin\\Debug\\etm-extract.exe -q\"select * from tb_big;\"", "r");
    if (fp == NULL) {
        printf("Failed to run command\n" );
        exit;
    }

    /* Read the output a line at a time - output it. */
    while (fgets(path, sizeof(path)-1, fp) != NULL) {
        printf("%s", path);
    }

    /* close */
    pclose(fp);

}

//starting_scheduler(argv[1]);

int main(int argc, char* argv[])
{


/*
	CreateMutexA(0, FALSE, "Local\\$myprogram$"); // try to create a named mutex
    if(GetLastError() == ERROR_ALREADY_EXISTS) // did the mutex already exist?
        return -1; // quit; mutex is released automatically
    */

	/* Vars */
//	HANDLE hMutex; // Mutex Handle
//	HWND hwndShow; // Find Window HWND
//
//	 /* Create A Mutex To Register Program Is Running */
//	 hMutex = CreateMutex(
//	     NULL,
//	     FALSE,
//	     "etmcore"
//	 );
//
//	 /* If Program Is Already Running, Show Program & Stop */
//	 if (hMutex) {
//
//	     if (GetLastError() == ERROR_ALREADY_EXISTS) {
//
//	 		//const char *WINCLASS_HERE;
//
//	 		char const *WINCLASS_HERE="etmcore";
//
//	 		//WINCLASS_HERE= (char*)malloc(sizeof(char)*10);
//
//			 //strcpy( WINCLASS_HERE, (char*)&"my");
//
//	         // Replace WINCLASS_HERE with name of your class
//	         hwndShow = FindWindow(WINCLASS_HERE, NULL);
//
//	         if (hwndShow) {
//
//	             // Minimize The Program So It Can Be Restored
//	             ShowWindow(hwndShow, SW_MINIMIZE);
//	             UpdateWindow(hwndShow);
//
//	             // Restore The Program In Its Original State
//	             ShowWindow(hwndShow, SW_RESTORE);
//	             UpdateWindow(hwndShow);
//
//	        }
//	        ExitProcess(1);
//
//	     }
//	 }





	char filenamejson[254];

	//strcpy( filenamejson, "C:\\workspace\\c\\etm-core\\bin\\Debug\\scheduler.txt" );

	strcpy( filenamejson, "C:\\workspace\\c\\etm-extract\\bin\Debug\\scheduler-extract.txt" );




    //filename = NULL;
    currentPath = (char*)malloc(sizeof(char)*strlen(argv[0]));

    //strcpy(currentPath,argv[0]);

    //currentPath=ExtractFilePath(currentPath,SEPARATE_DIR);


    currentPath="L:\\workspace\\c\\etm-extract\\bin\\Debug\\";

   // char *files="C:\\workspace\\c\\etm-extract\\bin\\Debug\\scheduler-extract.txt";
    char *files="C:\\workspace\\c\\etm-core\\bin\\Debug\\scheduler.txt";

    vector<scheduler_json> jobs;

	jobs    =   load_jobs(files);


	starting_jobs( jobs );

/*
	if(strcmp(argv[1], "-d") == 0){

		exit(EXIT_FAILURE);
		//printf("arg=%s\n\n", argv[1]);
		strcpy( filenamejson, "scheduler-extract.txt" );

	}else{

		strcpy( filenamejson, argv[1]);
	}
		*/

	system("PAUSE");

    return 0;
}
